package top.superflow.version.db

import java.util.concurrent.atomic.AtomicReference

import top.superflow.exception.RequestUnsupportedException
import top.superflow.version.compare.suggestion.Suggestion
import top.superflow.version.db.compare.{FieldExtraIncompatible, MatchMissingAndExtraField, MetadataConsistencySuggestion}

import scala.collection.mutable.{ListBuffer, Map}

trait FieldVersion extends Version{
  
  val name : AtomicReference[String] = new AtomicReference[String]
  
  val properties : Map[String, FieldPropertyVersion] = Map[String, FieldPropertyVersion]()
  
  
  def getId : String = {
    this.name.get
  }
  
  def compare (targetStructure : Any): Option[Suggestion] = {
    targetStructure match {
      case dvp : Option[_] =>{
        if(dvp == None || dvp.isEmpty){
          Some(new MetadataConsistencySuggestion(new FieldExtraIncompatible(this, null), new MatchMissingAndExtraField(this, null)))
        }else{
          this.compare(dvp.get)
        }
      }
      
      case fv: FieldVersion => {
        val suggestionsForChildren = getSuggestionsForChildren(fv)
        
        summarizeSuggestion(suggestionsForChildren)
      }
      
      case _ => {
        throw new RequestUnsupportedException(targetStructure)
      }
    }
    
  }
  
  def getSuggestionsForChildren (targetFieldVersion : FieldVersion): List[Suggestion] = {
    val possibleSuggestionList = ListBuffer[Suggestion]()
    
    for((propertyKey , propertyValue) <- this.properties){
      val propertyFromTarget = targetFieldVersion.getMatchedChild(propertyValue)
      val suggestionForChild = propertyValue.compare(propertyFromTarget)
      if(!suggestionForChild.isEmpty){
        possibleSuggestionList += suggestionForChild.get            
      }
    }
    
    possibleSuggestionList.toList
  }
  
  def getMatchedChild (childDataVersionKey : Any) : Option[Version] = {
    childDataVersionKey match {
      case property : FieldPropertyVersion => {
        this.properties.get(property.getPublicName())
      }
      
      case _ =>{
        None
      }
    }
  }
}